///PHILOTES Source Code.  (C)2012 PhiloLabs
#pragma once

#ifndef __Viewport_H__
#define __Viewport_H__

#include "OgrePrerequisites.h"
#include "OgreCommon.h"
#include "util/colourValue.h"
#include "OgreFrustum.h"

namespace Ogre {
	
	class _OgreExport Viewport : public MemAlloc_RenderSys
    {
    public:
		
		class _OgreExport Listener
		{
		public:
			virtual ~Listener() {}

			virtual void viewportCameraChanged(Viewport* viewport) {}

			virtual void viewportDimensionsChanged(Viewport* viewport) {}

			virtual void viewportDestroyed(Viewport* viewport) {}
		};

        
        Viewport(
            Camera* camera,
            RenderTarget* target,
            Real left, Real top,
            Real width, Real height,
            int ZOrder);

        
        virtual ~Viewport();

        
        void _updateDimensions(void);

        
        void update(void);
		
		
		void clear(unsigned int buffers = FBT_COLOUR | FBT_DEPTH,
				   const ColourValue& colour = ColourValue::Black, 
				   Real depth = 1.0f, unsigned short stencil = 0);

        
        RenderTarget* getTarget(void) const;

        
        Camera* getCamera(void) const;

        
        void setCamera(Camera* cam);

        
		int getZOrder(void) const;
		
        Real getLeft(void) const;

        
        Real getTop(void) const;

        

        Real getWidth(void) const;
        

        Real getHeight(void) const;
        

        int getActualLeft(void) const;
        

        int getActualTop(void) const;
        
        int getActualWidth(void) const;
        

        int getActualHeight(void) const;

        
        void setDimensions(Real left, Real top, Real width, Real height);

        
        void setOrientationMode(OrientationMode orientationMode, bool setDefault = true);

        
        OrientationMode getOrientationMode() const;

        
        static void setDefaultOrientationMode(OrientationMode orientationMode);

        
        static OrientationMode getDefaultOrientationMode();

        
        void setBackgroundColour(const ColourValue& colour);

        
        const ColourValue& getBackgroundColour(void) const;

		
        void setDepthClear( Real depth );

        
        Real getDepthClear(void) const;

        
        void setClearEveryFrame(bool clear, unsigned int buffers = FBT_COLOUR | FBT_DEPTH);

        
        bool getClearEveryFrame(void) const;

		
        unsigned int getClearBuffers(void) const;

		
		void setAutoUpdated(bool autoupdate);
		
		bool isAutoUpdated() const;

		
		void setMaterialScheme(const String& schemeName)
		{ mMaterialSchemeName = schemeName; }
		
		
		const String& getMaterialScheme(void) const
		{ return mMaterialSchemeName; }

		
        void getActualDimensions(
            int &left, int &top, int &width, int &height ) const;

        bool _isUpdated(void) const;
        void _clearUpdatedFlag(void);

        
        unsigned int _getNumRenderedFaces(void) const;

        
        unsigned int _getNumRenderedBatches(void) const;

        
        void setOverlaysEnabled(bool enabled);

        
        bool getOverlaysEnabled(void) const;

        
        void setSkiesEnabled(bool enabled);

        
        bool getSkiesEnabled(void) const;

        
        void setShadowsEnabled(bool enabled);

        
        bool getShadowsEnabled(void) const;


		
		void setVisibilityMask(uint32 mask) { mVisibilityMask = mask; }

		
		uint getVisibilityMask(void) const { return mVisibilityMask; }

		
		virtual void setRenderQueueInvocationSequenceName(const String& sequenceName);
		
		virtual const String& getRenderQueueInvocationSequenceName(void) const;
		/// Get the invocation sequence - will return null if using standard
		RenderQueueInvocationSequence* _getRenderQueueInvocationSequence(void);

        
        void pointOrientedToScreen(const Vector2 &v, int orientationMode, Vector2 &outv);
        void pointOrientedToScreen(Real orientedX, Real orientedY, int orientationMode,
                                   Real &screenX, Real &screenY);

		/// Add a listener to this camera
		void addListener(Listener* l);
		/// Remove a listener to this camera
		void removeListener(Listener* l);

    protected:
        Camera* mCamera;
        RenderTarget* mTarget;
        // Relative dimensions, irrespective of target dimensions (0..1)
        float mRelLeft, mRelTop, mRelWidth, mRelHeight;
        // Actual dimensions, based on target dimensions
        int mActLeft, mActTop, mActWidth, mActHeight;
        /// ZOrder
        int mZOrder;
        /// Background options
        ColourValue mBackColour;
		Real mDepthClearValue;
        bool mClearEveryFrame;
		unsigned int mClearBuffers;
        bool mUpdated;
        bool mShowOverlays;
        bool mShowSkies;
		bool mShowShadows;
		uint32 mVisibilityMask;
		// Render queue invocation sequence name
		String mRQSequenceName;
		RenderQueueInvocationSequence* mRQSequence;
		/// Material scheme
		String mMaterialSchemeName;
        /// Viewport orientation mode
        OrientationMode mOrientationMode;
        static OrientationMode mDefaultOrientationMode;

		/// Automatic rendering on/off
		bool mIsAutoUpdated;

		typedef vector<Listener*>::type ListenerList;
		ListenerList mListeners;
    };
	
	

}

#endif
